#include "oled_font.h"	
#include "oled.h"		
#include "Base_i2c.h"
#include "string.h"

#define LEFT 			0x27
#define RIGHT 		0x26
#define UP 				0X29
#define DOWN 			0x2A  // 修正拼写
#define ON				0xA7
#define OFF				0xA6

#define OLED_Addr    0x78

uint16_t const displayWidth                = 128;
uint16_t const displayHeight               = 64;

static uint8_t OLED_RAM[8][128];

// 修正形参命名为小驼峰
void HW_OLED_WriteByte(uint8_t regAddr, uint8_t data) {
    uint8_t TxData[2] = {regAddr, data};
	Base_I2C_WriteCmd(&hi2c1, OLED_Addr, (uint8_t*)TxData, 2, 10);
}

// 修正形参命名为小驼峰
void HW_OLED_WriteCmd(uint8_t iicCommand) {
    HAL_I2C_WriteByte(0x00, iicCommand);
}

// 修正形参命名为小驼峰
void HW_OLED_WriteDat(uint8_t iicData) {
    HAL_I2C_WriteByte(0x40, iicData);
}

void HW_OLED_Init(void) { 
    HAL_Delay(500);
    
    HW_OLED_WriteCmd(0xAE); 
    HW_OLED_WriteCmd(0x20);	
	
    HW_OLED_WriteCmd(0x10);	
    HW_OLED_WriteCmd(0xb0);	
    HW_OLED_WriteCmd(0x00); 
    HW_OLED_WriteCmd(0x10); 

    HW_OLED_WriteCmd(0xc8);	
    HW_OLED_WriteCmd(0x40); 
    HW_OLED_WriteCmd(0x81); 
    HW_OLED_WriteCmd(0xff); 
    HW_OLED_WriteCmd(0xa1); 
    HW_OLED_WriteCmd(0xa6); 
    HW_OLED_WriteCmd(0xa8); 
    HW_OLED_WriteCmd(0x3F); 
    HW_OLED_WriteCmd(0xa4); 
    HW_OLED_WriteCmd(0xd3); 
    HW_OLED_WriteCmd(0x00); 
    HW_OLED_WriteCmd(0xd5); 
    HW_OLED_WriteCmd(0xf0); 
    HW_OLED_WriteCmd(0xd9); 
    HW_OLED_WriteCmd(0x22); 
    HW_OLED_WriteCmd(0xda); 
    HW_OLED_WriteCmd(0x12);
    HW_OLED_WriteCmd(0xdb); 
    HW_OLED_WriteCmd(0x20); 
    HW_OLED_WriteCmd(0x8d); 
    HW_OLED_WriteCmd(0x14); 
    HW_OLED_WriteCmd(0xaf); 
    
    HW_OLED_FullyClear();
}

void HW_OLED_On(void) {
    HW_OLED_WriteCmd(0X8D);  
    HW_OLED_WriteCmd(0X14);  
    HW_OLED_WriteCmd(0XAF); 
}

void HW_OLED_Off(void) {
    HW_OLED_WriteCmd(0X8D); 
    HW_OLED_WriteCmd(0X10); 
    HW_OLED_WriteCmd(0XAE); 
}

void HW_OLED_RefreshRAM(void) {
    for(uint16_t m = 0; m < displayHeight/8; m++) {
        HW_OLED_WriteCmd(0xb0 + m);	
        HW_OLED_WriteCmd(0x00);		
        HW_OLED_WriteCmd(0x10);	
        for(uint16_t n = 0; n < displayWidth; n++) {
            HW_OLED_WriteDat(OLED_RAM[m][n]);
        }
    } 
}

// 修正语法：直接初始化数组，去掉错误循环
void HW_OLED_ClearRAM(void) {
    memset(OLED_RAM, 0x00, sizeof(OLED_RAM));
}

void HW_OLED_FullyFill(uint8_t fillData) {
    for(uint16_t m = 0; m < displayHeight/8; m++) {
        for(uint16_t n = 0; n < displayWidth; n++) {
            OLED_RAM[m][n] = fillData;
        }
    }
    HW_OLED_RefreshRAM();
}

void HW_OLED_FullyClear(void) {
    HW_OLED_FullyFill(RESET_PIXEL);
}

void HW_OLED_SetPixel(int16_t x, int16_t y, uint8_t setPixel) { 
    if (x >= 0 && x < displayWidth && y >= 0 && y < displayHeight) {
        if (setPixel) {
            OLED_RAM[y/8][x] |= (0x01 << (y%8));
        } else {
            OLED_RAM[y/8][x] &= ~(0x01 << (y%8));
        }
    }
}

PixelStatus HW_OLED_GetPixel(int16_t x, int16_t y) {
    if (OLED_RAM[y/8][x] >> (y%8) & 0x01)
        return SET_PIXEL;
    return RESET_PIXEL;
}

// 修正形参命名：ch → str，TextSize → textSize
void HW_OLED_ShowStr(int16_t x, int16_t y, uint8_t str[], uint8_t textSize) { 
    if (x >= 0 && x < displayWidth && y >= 0 && y < displayHeight) {
        int32_t c = 0;
        uint8_t j = 0;
        switch (textSize) {
            case 1: {
                while (str[j] != '\0') {
                    c = str[j] - 32;
                    if (c < 0)
                        break;
                    
                    if (x >= 125 || (127 - x < 6)) {
                        x = 0;
                        y += 8;
                        if (63 - y < 8)	
                            break;
                    }
                    for (uint8_t m = 0; m < 6; m++) {
                        for (uint8_t n = 0; n < 8; n++) {
                            HW_OLED_SetPixel(x + m, y + n, (F6x8[c][m] >> n) & 0x01);
                        }
                    }
                    x += 6;
                    j++;
                }
            } break;
            case 2: {
                while (str[j] != '\0') {
                    c = str[j] - 32;
                    if (c < 0)
                        break;
                    
                    if (x >= 127 || (127 - x < 8)) {
                        x = 0;
                        y += 16;
                        if (63 - y < 16)
                            break;
                    }
                    for (uint8_t m = 0; m < 2; m++) {
                        for (uint8_t n = 0; n < 8; n++) {
                            for (uint8_t i = 0; i < 8; i++) {
                                HW_OLED_SetPixel(x + n, y + i + m*8, (F8X16[c][n + m*8] >> i) & 0x01);
                            }
                        }	
                    }
                    x += 8;
                    j++;
                }
            } break;
        }
    }
    HW_OLED_RefreshRAM();
}

void HW_OLED_ShowCN(int16_t x, int16_t y, uint8_t* str) {
    if (x >= 0 && x < displayWidth && y >= 0 && y < displayHeight) {
        int32_t  len = 0, offset = sizeof(F16x16_CN[0].index);
        
        while (str[len] != '\0') {
            if (x >= 127 || (127 - x < 16)) {
                x = 0;
                y += 16;
                if (63 - y < 16)
                    break;
            }
            for (uint8_t i = 0; i < sizeof(F16x16_CN)/sizeof(GB2312_CN); i++) {
                if (((F16x16_CN[i].index[0] == str[len]) && (F16x16_CN[i].index[1] == str[len+1]))) {
                    for (uint8_t m = 0; m < 2; m++) {
                        for (uint8_t n = 0; n < 16; n++) {
                            for (uint8_t j = 0; j < 8; j++) {
                                HW_OLED_SetPixel(x + n, y + j + m*8, (F16x16_CN[i].encoder[n + m*16] >> j) & 0x01);
                            }
                        }
                    }			
                    x += 16;
                    len += offset;
                    break;
                }
                else if (F16x16_CN[i].index[0] == str[len] && str[len] == 0x20) {
                    for (uint8_t m = 0; m < 2; m++) {
                        for (uint8_t n = 0; n < 16; n++) {
                            for (uint8_t j = 0; j < 8; j++) {
                                HW_OLED_SetPixel(x + n, y + j + m*8, (F16x16_CN[i].encoder[n + m*16] >> j) & 0x01);
                            }								
                        }	
                    }			
                    x += 16;
                    len++;
                    break;
                }
            }
        }
    }
    HW_OLED_RefreshRAM();
}

void HW_OLED_ShowMixedCH(int16_t x, int16_t y, uint8_t* str) {
    if (x >= 0 && x < displayWidth && y >= 0 && y < displayHeight) {
        int32_t len = 0, c, offset = sizeof(F16x16_CN[0].index);

        while (str[len] != '\0') {
            if (str[len] >= 0xa1) {
                for (uint8_t i = 0; i < sizeof(F16x16_CN)/sizeof(GB2312_CN); i++) {
                    if (((F16x16_CN[i].index[0] == str[len]) && (F16x16_CN[i].index[1] == str[len+1]))) {
                        if (x >= 127 || (127 - x < 16)) {
                            x = 0;
                            y += 16;
                            if (63 - y < 16)	
                                break;
                        }
                        for (uint8_t m = 0; m < 2; m++) {
                            for (uint8_t n = 0; n < 16; n++) {
                                for (uint8_t j = 0; j < 8; j++) {
                                    HW_OLED_SetPixel(x + n, y + j + m*8, (F16x16_CN[i].encoder[n + m*16] >> j) & 0x01);
                                }		
                            }								
                        }			
                        x += 16;
                        len += offset;
                        break;
                    }
                }
            }
            else if (str[len] <= 127) {
                c = str[len] - 32;
                if (c < 0)	
                    break;
                if (x >= 127 || (127 - x < 8)) {
                    x = 0;
                    y += 16;
                    if (63 - y < 16)	
                        break;
                }
                for (uint8_t m = 0; m < 2; m++) {
                    for (uint8_t n = 0; n < 8; n++) {
                        for (uint8_t i = 0; i < 8; i++) {
                            HW_OLED_SetPixel(x + n, y + i + m*8, (F8X16[c][n + m*8] >> i) & 0x01);
                        }
                    }
                }
                x += 8;
                len++;
            }
        }
    }
    HW_OLED_RefreshRAM();
}

// 修正形参命名：L → width，H → height，BMP → bmpData
void HW_OLED_DrawBMP(int16_t x0, int16_t y0, int16_t width, int16_t height, const uint8_t bmpData[]) {
    if (x0 >= 0 && x0 < displayWidth && x0 + width <= displayWidth &&
        y0 >= 0 && y0 < displayHeight && y0 + height <= displayHeight) {		
        uint8_t *p = (uint8_t *)bmpData;
        for(int16_t y = y0; y < y0 + height; y +=8) {
            for(int16_t x = x0; x < x0 + width; x++) {
                for(int16_t i = 0; i < 8; i++) {
                    HW_OLED_SetPixel(x, y + i, ((*p) >> i) & 0x01);
                }
                p++;
            }
        }
    }
    HW_OLED_RefreshRAM();
}

// 修正形参命名：L → width，H → height
void OLED_AreaFill(int16_t x0, int16_t y0, int16_t width, int16_t height, uint8_t fillData) {
    if (x0 >= 0 && x0 < displayWidth && x0 + width <= displayWidth &&
        y0 >= 0 && y0 < displayHeight && y0 + height <= displayHeight) {		
        for(int16_t y = y0; y < y0 + height; y++) {
            for(int16_t x = x0; x < x0 + width; x++) {
                for(int16_t i = 0; i < 8; i++) {
                    HW_OLED_SetPixel(x, y + i, (fillData >> i) & SET_PIXEL);
                }
            }
        }
        HW_OLED_RefreshRAM();
    }
}

// 修正形参命名：L → width，H → height
void OLED_AreaClear(int16_t x0, int16_t y0, int16_t width, int16_t height) {
    if (x0 >= 0 && x0 < displayWidth && x0 + width <= displayWidth &&
        y0 >= 0 && y0 < displayHeight && y0 + height <= displayHeight) {		
        for(int16_t y = y0; y < y0 + height; y +=8) {
            for(int16_t x = x0; x < x0 + width; x++) {
                for(int16_t i = 0; i < 8; i++) {
                    HW_OLED_SetPixel(x, y + i, RESET_PIXEL);
                }
            }
        }		
        HW_OLED_RefreshRAM();
    }
}

void HW_OLED_FullyToggle(void) {
    for(uint16_t m = 0; m < displayHeight/8; m++) {
        for(uint16_t n = 0; n < displayWidth; n++) {
            OLED_RAM[m][n] = ~OLED_RAM[m][n];
        }
    }
    HW_OLED_RefreshRAM();
}

// 修正形参命名：L → width，H → height
void HW_OLED_AreaToggle(int16_t x0, int16_t y0, int16_t width, int16_t height) {
    if (x0 >= 0 && x0 < displayWidth && x0 + width <= displayWidth &&
        y0 >= 0 && y0 < displayHeight && y0 + height <= displayHeight) {	
        for(int16_t y = y0; y < y0 + height; y +=8) {
            for(int16_t x = x0; x < x0 + width; x++) {
                for(int16_t i = 0; i < 8; i++) {
                    HW_OLED_SetPixel(x, y + i, !HW_OLED_GetPixel(x, y + i));
                }
            }
        }		
        HW_OLED_RefreshRAM();
    }
}

void HW_OLED_VerticalShift(void) {
    for(uint8_t i = 0; i < displayHeight; i++) {
        HW_OLED_WriteCmd(0xd3);
        HW_OLED_WriteCmd(i);
        HAL_Delay(40);
    }
}

void HW_OLED_HorizontalShift(uint8_t direction) {
    HW_OLED_WriteCmd(direction);
    HW_OLED_WriteCmd(0x00);
    HW_OLED_WriteCmd(0x00);
    HW_OLED_WriteCmd(0x05);
    HW_OLED_WriteCmd(0x07);
    HW_OLED_WriteCmd(0x00);
    HW_OLED_WriteCmd(0xff);
    HW_OLED_WriteCmd(0x2f);
}

void HW_OLED_VerticalAndHorizontalShift(uint8_t direction) {
    HW_OLED_WriteCmd(direction);
    HW_OLED_WriteCmd(0x00);
    HW_OLED_WriteCmd(0x00);
    HW_OLED_WriteCmd(0x05);
    HW_OLED_WriteCmd(0x07);
    HW_OLED_WriteCmd(0x01);
    HW_OLED_WriteCmd(0x2f);
}

void HW_OLED_DisplayMode(uint8_t mode) {
    HW_OLED_WriteCmd(mode);
}

void HW_OLED_IntensityControl(uint8_t intensity) {
    HW_OLED_WriteCmd(0x81);
    HW_OLED_WriteCmd(intensity);
}

